the inefficent loop
This loop runs through the netcdf files and then looks for which rows in data_aea it should extract the value to point from, and at what depth (netcDF layer)
strt <- Sys.time() #get the start time
xy <- testbk190000[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbk190000sp <- SpatialPointsDataFrame(coords = xy, data = testbk190000, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 2007 # a variable for the observation year
mth <- 10 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbk190000sp)) {
de <- testbk190000sp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbk190000sp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$temp_depth[j] <- NA
} else
testbk190000sp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbk190000sp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$salinity_depth[j] <- NA
} else
testbk190000sp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbk190000sp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$chl_depth[j] <- NA
} else
testbk190000sp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbk190000sp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$o2_depth[j] <- NA
} else
testbk190000sp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbk190000sp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbk190000sp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
}
}
}
[1] "2007_10_chl.nc"
plot each variable against the different no of backgrounn points
test190000 <- as.data.frame(testbk19000sp)
Error in as.data.frame(testbk19000sp) : object 'testbk19000sp' not found
ggplot(test10000, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/ssh_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/mlp_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

Try again for another month - say 1999 02 AND again 2014 06
This time extract the values for all points and then subset
strt <- Sys.time() #get the start time
xy <- testbglist[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbglistsp <- SpatialPointsDataFrame(coords = xy, data = testbglist, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 1999 # a variable for the observation year
mth <- 02 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbglistsp)) {
de <- testbglistsp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbglistsp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$temp_depth[j] <- NA
} else
testbglistsp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbglistsp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$salinity_depth[j] <- NA
} else
testbglistsp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbglistsp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$chl_depth[j] <- NA
} else
testbglistsp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbglistsp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$o2_depth[j] <- NA
} else
testbglistsp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbglistsp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbglistsp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
}
}
}
[1] "1999_02_chl.nc"
[1] "1999_02_mlp.nc"
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
[1] "1999_02_o2.nc"
[1] "1999_02_salinity.nc"
[1] "1999_02_ssh.nc"
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
[1] "1999_02_temp.nc"
write.csv(testbglistsp, "../data/env/background_point_check/1999_02/testbglistoutput.csv", row.names = FALSE)
#test_back_df <- as.data.frame(testbk100000sp)
#head(test_back_df)
print(Sys.time()-strt) #time it took to run
Time difference of 3.277501 hours
ok now create the first lot of random for 1999_02
testbk100001999 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200001999 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300001999 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500001999 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000001999 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900001999 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk100001999, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/ssh_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/mlp_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_surface_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_depth_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_surface_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_depth_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_surface_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_depth_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500001999 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_surface_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500001999 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_depth_back_no_1999.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
And now 2014_06
#head(test_back_df)
print(Sys.time()-strt) #time it took to run
Time difference of 3.455486 hours
ok now create the first lot of random for 2014_06
testbk100002014 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200002014 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300002014 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500002014 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000002014 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900002014 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk100002014, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/ssh_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/mlp_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_surface_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_depth_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_surface_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_depth_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_surface_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_depth_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_surface_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_depth_back_no_2014.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
LS0tDQp0aXRsZTogImJhY2tncm91bmQgcG9pbnRzIC0gaXMgbW9yZSBiZXR0ZXI/Ig0KYXV0aG9yOiAiU2FtYW50aGEgQW5kcmV3cyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KIyBPdmVydmlldw0KcXVpY2sgdGVzdCB0byBzZWUgd2hhdCBoYXBwZW5zIHRvIGRpc3RyaWJ1dGlvbiBvZiBlbnYuIHZhcmlhYmxlcyBpZiBhZGQgbW9yZSBiYWNrZ3JvdW5kIHBvaW50cyAoaXMgMTBrIGVub3VnaCBvciBkbyBJIG5lZWQgbW9yZSkNCg0KQSBub3RlIHRvIGFueW9uZSB3aG8gbWlnaHQgaGFwcGVuIHRvIHN0dW1ibGUgYWNyb3NzIHRoaXMuLi4gSSBhbSBhIGJlZ2lubmVyIGluIFIgYW5kIGhhdmUgaGFkIG5vIGV4cG9zdXJlIHRvIHNpbWlsYXIgbGFuZ3VhZ2VzLiBJIGRvbid0IGtub3cgd2hhdCBJJ20gZG9pbmcuIFRoZSBjb2RlIGhlcmVpbiBpcyB1bmxpa2VseSB0byBiZSBlbGVnYW50IGFuZCB0aGVyZSBhcmUgcHJvYmFibHkgbW9yZSBlZmZpY2llbnQgd2F5cyBvZiBydW5uaW5nIHRoZSBjb2RlLg0KDQpCdWlsdCB3aXRoICdyIGdldFJ2ZXJzaW9uKCknLg0KDQojIFBhY2thZ2UgZGVwZW5kZW5jaWVzDQpZb3UgY2FuIGxvYWQgdGhlbSB1c2luZyB0aGUgZm9sbG93aW5nIGNvZGUgd2hpY2ggdXNlcyBhIGZ1bmN0aW9uIGNhbGxlZCBbaXBha10oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vc3RldmVud29ydGhpbmd0b24vMzE3ODE2MykuIA0KTm90ZSB0aGlzIGZ1bmN0aW9uIGNoZWNrcyB0byBzZWUgaWYgdGhlIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQgZmlyc3QuDQpUaGUgImluY2x1ZGU9RkFMU0UiIHN1cHJlc3NlcyB0aGUgcGFja2FnZSBpbnN0YWxsYXRpb24gdGV4dCBhcHBlYXJpbmcgaW4gdGhlIGRvY3VtZW50Li4uDQpgYGB7ciBwcmUtaW5zdGFsbCBwYWNrYWdlcywgaW5jbHVkZT1GQUxTRX0NCnBhY2thZ2VzIDwtIGMoIm5jZGY0IiwgInJhc3RlciIsICJnZ3Bsb3QyIiwgInBsb3RseSIpIA0Kc291cmNlKCIuLi9zcmMvaXBhay5SIikNCmlwYWsocGFja2FnZXMpDQpgYGANCg0KbG9hZCBvbmUgb2YgdGhlIHJhdyBiYWNrZ3JvdW5kLmNzdiBmaWxlcyB0byByYW5kb21seSBleHRyYWN0IHBvaW50cyBmcm9tIChub3RlIHRoYXQgdGhlc2UgZmlsZXMgZG8gbm90IGluY2x1ZGUgcHJlc2VuY2UgY2VsbHMsIGJ1dCB3aWxsIGRvIGZvciB0aGlzIHRlc3QpDQoNCmBgYHtyfQ0KdGVzdGJnbGlzdCA8LSByZWFkLmNzdigiLi4vb3V0cHV0L2Jpby9iYWNrZ3JvdW5kL3Jhdy8yMDA2LjIuY3N2IiwgaGVhZGVyID0gVFJVRSkNCmhlYWQodGVzdGJnbGlzdCkNCmBgYA0KDQpOb3cgY3JlYXRlIGEgYnVuY2ggb2YgZGF0YWZyYW1lcyB3aXRoIGRpZmZlcmVudCBubyBvZiByYW5kb20gY2VsbHMgc2VsZWN0ZWQNCg0KU0FNIC0gQSBCRVRURVIgV0FZIFdPVUxEIEhBVkUgQkVFTiBUTyBSVU4gVEhFIExPT1AgT04gQUxMIFRIRSBQT0lOVFMsIFRIRU4gUkFORE9NTFkgU0VMRUNUIChRVUlDS0VSKQ0KDQpgYGB7cn0NCnRlc3RiazEwMDAwIDwtIHRlc3RiZ2xpc3Rbc2FtcGxlKG5yb3codGVzdGJnbGlzdCksIDEwMDAwKSwgXSAgI3doZXJlIDEwMDAwID0gbnVtYmVyIG9mIHJvd3MgdG8gc2FtcGxlIChsYXJnZSBzYW1wbGUgYXMgcGVyIG1heGVudCkNCnRlc3RiazIwMDAwIDwtIHRlc3RiZ2xpc3Rbc2FtcGxlKG5yb3codGVzdGJnbGlzdCksIDIwMDAwKSwgXSAgDQp0ZXN0YmszMDAwMCA8LSB0ZXN0YmdsaXN0W3NhbXBsZShucm93KHRlc3RiZ2xpc3QpLCAzMDAwMCksIF0gIA0KdGVzdGJrNTAwMDAgPC0gdGVzdGJnbGlzdFtzYW1wbGUobnJvdyh0ZXN0YmdsaXN0KSwgNTAwMDApLCBdICANCnRlc3RiazEwMDAwMCA8LSB0ZXN0YmdsaXN0W3NhbXBsZShucm93KHRlc3RiZ2xpc3QpLCAxMDAwMDApLCBdICANCnRlc3RiazE5MDAwMCA8LSB0ZXN0YmdsaXN0W3NhbXBsZShucm93KHRlc3RiZ2xpc3QpLCAxOTAwMDApLCBdICANCmBgYA0KDQoNCg0KIyB0aGlzIHRlc3Qgd2lsbCB1c2UgYSBzaG9ydGVyIGRhdGFzZXQgYW5kIGEgc21hbGxlciBudW1iZXIgb2YgbmV0Y2Rmcw0KIyB0aGUgaW5lZmZpY2VudCBsb29wDQoNCg0KDQpUaGlzIGxvb3AgcnVucyB0aHJvdWdoIHRoZSBuZXRjZGYgZmlsZXMgYW5kIHRoZW4gbG9va3MgZm9yIHdoaWNoIHJvd3MgaW4gZGF0YV9hZWEgaXQgc2hvdWxkIGV4dHJhY3QgdGhlIHZhbHVlIHRvIHBvaW50IGZyb20sIGFuZCBhdCB3aGF0IGRlcHRoIChuZXRjREYgbGF5ZXIpDQoNCmBgYHtyfQ0Kc3RydCA8LSBTeXMudGltZSgpICNnZXQgdGhlIHN0YXJ0IHRpbWUNCg0KeHkgPC0gdGVzdGJrMTkwMDAwWyAsYygibG9uZ2l0dWRlXyIsImxhdGl0dWRlX20iKV0gIyBUaGlzIGlzIHRvIHRlbGwgUiB3aGVyZSB0aGUgY29vcmRpbmF0ZXMgYXJlLiBOb3RlIHRoYXQgdGhlIGNvbHVtbiBvcmRlciBuZWVkcyB0byBiZSBsb25naXR1ZGUsIGxhdGl0dWRlDQp0ZXN0YmsxOTAwMDBzcCA8LSBTcGF0aWFsUG9pbnRzRGF0YUZyYW1lKGNvb3JkcyA9IHh5LCBkYXRhID0gdGVzdGJrMTkwMDAwLCBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9YWVhICtsYXRfMT01MCArbGF0XzI9NzAgK2xhdF8wPTQwICtsb25fMD0tNjAgK3hfMD0wICt5XzA9MCArZWxscHM9R1JTODAgK2RhdHVtPU5BRDgzICt1bml0cz1tICtub19kZWZzIikpICMgVGhlIENSUyBpcyB1c2VkIGhlcmUgaXMgZm9yIHRoZSBhbGJlcnMgZXF1YWwgYXJlYSBwcm9qZWN0aW9uLg0KDQoNCm5ldGNkZl9saXN0IDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IFRSVUUpICN0cnVlIG1lYW5zIHRoZSBmdWxsIHBhdGggaXMgaW5jbHVkZWQNCm5vX25ldGNkZiA8LSBsZW5ndGgobmV0Y2RmX2xpc3QpICNmb3IgdGhlIGxvb3AgLSBuZWVkIHRvIGtub3cgaG93IG1hbnkgZmlsZXMgdG8gY3ljbGUgdGhyb3VnaA0KbmV0Y2RmX25hbWUgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9ia3RzdG5jZGYiLCBwYXR0ZXJuID0gJyoubmMnLCBmdWxsLm5hbWVzID0gRkFMU0UpICNmYWxzZSBtZWFucyB0aGUgcGF0aCBpcyBub3QgaW5jbHVkZWQNCmFlYSA8LSByYXN0ZXIoIi4uL291dHB1dC9lbnYvYWVhLnRpZiIpIA0KeXIgPC0gMjAwNyAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24geWVhcg0KbXRoIDwtIDEwICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiBtb250aA0KDQpmb3IgKGkgaW4gMTpub19uZXRjZGYpIHsgIA0KICBwcmludChuZXRjZGZfbmFtZVtpXSkgI3RoaXMganVzdCBwcmludHMgdGhlIG5hbWUgb2YgdGhlIG5ldENERiBSIGlzIHdvcmtpbmcgb25lDQogIGJya3lyIDwtIGFzLmludGVnZXIoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAxKSkgIyBleHRyYWN0aW5nIHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBuZXRjZGYgZmlsZW5hbWUgKHdoaWNoIGlzIHRoZSB5ZWFyKQ0KICBicmttdGggPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDIpKSAjIGV4dHJhY3RpbmcgdGhlIHNlY29uZCBwYXJ0IG9mIHRoZSBuZXRjZGYgZmlsZW5hbWUgKHdoaWNoIGlzIHRoZSBtb250aCkNCiAgYnJrdmFyIDwtIChzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDMpKSAjIGV4dHJhY3RpbmcgdGhlIHRoaXJkIHBhcnQgb2YgdGhlIG5ldGNkZiAoaW5jLm5jKQ0KICB0ZW1wX2JyaWNrIDwtIGJyaWNrKG5ldGNkZl9saXN0W2ldLCBsdmFyID0gNCkNCiAgdGVtcF9icmljayA8LSBwcm9qZWN0UmFzdGVyKHRlbXBfYnJpY2ssIGFlYSkgDQogICAgZm9yIChqIGluIDE6bnJvdyh0ZXN0YmsxOTAwMDBzcCkpIHsgIA0KICAgICAgZGUgPC0gdGVzdGJrMTkwMDAwc3AkZGVwdGhsYXllcm5vW1tqXV0gICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIGRlcHRoIGxheWVyDQogICAgICAgICAgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAidGVtcC5uYyIpew0KICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCR0ZW1wX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCR0ZW1wX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3AkdGVtcF9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNhbGluaXR5Lm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRzYWxpbml0eV9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmsxOTAwMDBzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJjaGwubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJGNobF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmsxOTAwMDBzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3AkY2hsX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3AkY2hsX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJrMTkwMDAwc3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm8yLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRvMl9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmsxOTAwMDBzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3AkbzJfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRvMl9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJtbHAubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJG1scF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmsxOTAwMDBzcFtqLCBdKQ0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJzc2gubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJHNzaF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmsxOTAwMDBzcFtqLCBdKSANCiAgICAgICAgICAgIA0KICAgICAgICAgIH0NCiAgICAgDQogICAgfQ0KfQ0Kd3JpdGUuY3N2KHRlc3RiazE5MDAwMHNwLCAiLi4vZGF0YS90ZXN0YmsxOTAwMDBvdXRwdXQuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQojdGVzdF9iYWNrX2RmIDwtIGFzLmRhdGEuZnJhbWUodGVzdGJrMTAwMDAwc3ApDQojaGVhZCh0ZXN0X2JhY2tfZGYpDQpwcmludChTeXMudGltZSgpLXN0cnQpICN0aW1lIGl0IHRvb2sgdG8gcnVuDQpgYGANCg0KDQpwbG90IGVhY2ggdmFyaWFibGUgYWdhaW5zdCB0aGUgZGlmZmVyZW50IG5vIG9mIGJhY2tncm91bm4gcG9pbnRzDQoNCmBgYHtyfQ0KdGVzdDEwMDAwIDwtIGFzLmRhdGEuZnJhbWUodGVzdGJrMTAwMDBzcCkNCnRlc3QyMDAwMCA8LSBhcy5kYXRhLmZyYW1lKHRlc3RiazIwMDAwc3ApDQp0ZXN0NTAwMDAgPC0gYXMuZGF0YS5mcmFtZSh0ZXN0Yms1MDAwMHNwKQ0KdGVzdDEwMDAwMCA8LSBhcy5kYXRhLmZyYW1lKHRlc3RiazEwMDAwc3ApDQp0ZXN0MTkwMDAwIDwtIGFzLmRhdGEuZnJhbWUodGVzdGJrMTkwMDAwc3ApDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IHNzaF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL3NzaF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IG1scF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL21scF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IHRlbXBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vZGF0YS90ZW1wX3N1cmZhY2VfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3QxMDAwMCwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL3RlbXBfZGVwdGhfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3QxMDAwMCwgYWVzKHggPSBzYWxpbml0eV9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL3NhbGluaXR5X3N1cmZhY2VfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3QxMDAwMCwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vZGF0YS9zYWxpbml0eV9kZXB0aF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL2NobF9zdXJmYWNlX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gY2hsX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL2NobF9kZXB0aF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IG8yX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvbzJfc3VyZmFjZV9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL28yX2RlcHRoX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQpgYGANCg0KVHJ5IGFnYWluIGZvciBhbm90aGVyIG1vbnRoIC0gc2F5IDE5OTkgMDIgQU5EIGFnYWluIDIwMTQgMDYNCg0KVGhpcyB0aW1lIGV4dHJhY3QgdGhlIHZhbHVlcyBmb3IgYWxsIHBvaW50cyBhbmQgdGhlbiBzdWJzZXQNCg0KYGBge3J9DQpzdHJ0IDwtIFN5cy50aW1lKCkgI2dldCB0aGUgc3RhcnQgdGltZQ0KDQp4eSA8LSB0ZXN0YmdsaXN0WyAsYygibG9uZ2l0dWRlXyIsImxhdGl0dWRlX20iKV0gIyBUaGlzIGlzIHRvIHRlbGwgUiB3aGVyZSB0aGUgY29vcmRpbmF0ZXMgYXJlLiBOb3RlIHRoYXQgdGhlIGNvbHVtbiBvcmRlciBuZWVkcyB0byBiZSBsb25naXR1ZGUsIGxhdGl0dWRlDQp0ZXN0YmdsaXN0c3AgPC0gU3BhdGlhbFBvaW50c0RhdGFGcmFtZShjb29yZHMgPSB4eSwgZGF0YSA9IHRlc3RiZ2xpc3QsIHByb2o0c3RyaW5nID0gQ1JTKCIrcHJvaj1hZWEgK2xhdF8xPTUwICtsYXRfMj03MCArbGF0XzA9NDAgK2xvbl8wPS02MCAreF8wPTAgK3lfMD0wICtlbGxwcz1HUlM4MCArZGF0dW09TkFEODMgK3VuaXRzPW0gK25vX2RlZnMiKSkgIyBUaGUgQ1JTIGlzIHVzZWQgaGVyZSBpcyBmb3IgdGhlIGFsYmVycyBlcXVhbCBhcmVhIHByb2plY3Rpb24uDQoNCg0KbmV0Y2RmX2xpc3QgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9ia3RzdG5jZGYiLCBwYXR0ZXJuID0gJyoubmMnLCBmdWxsLm5hbWVzID0gVFJVRSkgI3RydWUgbWVhbnMgdGhlIGZ1bGwgcGF0aCBpcyBpbmNsdWRlZA0Kbm9fbmV0Y2RmIDwtIGxlbmd0aChuZXRjZGZfbGlzdCkgI2ZvciB0aGUgbG9vcCAtIG5lZWQgdG8ga25vdyBob3cgbWFueSBmaWxlcyB0byBjeWNsZSB0aHJvdWdoDQpuZXRjZGZfbmFtZSA8LSBsaXN0LmZpbGVzKCIuLi9kYXRhL2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBGQUxTRSkgI2ZhbHNlIG1lYW5zIHRoZSBwYXRoIGlzIG5vdCBpbmNsdWRlZA0KYWVhIDwtIHJhc3RlcigiLi4vb3V0cHV0L2Vudi9hZWEudGlmIikgDQp5ciA8LSAxOTk5ICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiB5ZWFyDQptdGggPC0gMDIgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIG1vbnRoDQoNCmZvciAoaSBpbiAxOm5vX25ldGNkZikgeyAgDQogIHByaW50KG5ldGNkZl9uYW1lW2ldKSAjdGhpcyBqdXN0IHByaW50cyB0aGUgbmFtZSBvZiB0aGUgbmV0Q0RGIFIgaXMgd29ya2luZyBvbmUNCiAgYnJreXIgPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDEpKSAjIGV4dHJhY3RpbmcgdGhlIGZpcnN0IHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIHllYXIpDQogIGJya210aCA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMikpICMgZXh0cmFjdGluZyB0aGUgc2Vjb25kIHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIG1vbnRoKQ0KICBicmt2YXIgPC0gKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMykpICMgZXh0cmFjdGluZyB0aGUgdGhpcmQgcGFydCBvZiB0aGUgbmV0Y2RmIChpbmMubmMpDQogIHRlbXBfYnJpY2sgPC0gYnJpY2sobmV0Y2RmX2xpc3RbaV0sIGx2YXIgPSA0KQ0KICB0ZW1wX2JyaWNrIDwtIHByb2plY3RSYXN0ZXIodGVtcF9icmljaywgYWVhKSANCiAgICBmb3IgKGogaW4gMTpucm93KHRlc3RiZ2xpc3RzcCkpIHsgIA0KICAgICAgZGUgPC0gdGVzdGJnbGlzdHNwJGRlcHRobGF5ZXJub1tbal1dICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiBkZXB0aCBsYXllcg0KICAgICAgICAgIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInRlbXAubmMiKXsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNhbGluaXR5Lm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc2FsaW5pdHlfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gImNobC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJvMi5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG8yX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJtbHAubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRtbHBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNzaC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNzaF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICANCiAgICAgICAgICB9DQogICAgIA0KICAgIH0NCn0NCndyaXRlLmNzdih0ZXN0YmdsaXN0c3AsICIuLi9kYXRhL2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTlfMDIvdGVzdGJnbGlzdG91dHB1dC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCnRlc3RfYmFja19kZiA8LSBhcy5kYXRhLmZyYW1lKHRlc3RiZ2xpc3RzcCkNCiNoZWFkKHRlc3RfYmFja19kZikNCnByaW50KFN5cy50aW1lKCktc3RydCkgI3RpbWUgaXQgdG9vayB0byBydW4NCmBgYA0KDQpvayBub3cgY3JlYXRlIHRoZSBmaXJzdCBsb3Qgb2YgcmFuZG9tIGZvciAxOTk5XzAyDQoNCmBgYHtyfQ0KdGVzdGJrMTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMCksIF0gICN3aGVyZSAxMDAwMCA9IG51bWJlciBvZiByb3dzIHRvIHNhbXBsZSAobGFyZ2Ugc2FtcGxlIGFzIHBlciBtYXhlbnQpDQp0ZXN0YmsyMDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDIwMDAwKSwgXSAgDQp0ZXN0YmszMDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDMwMDAwKSwgXSAgDQp0ZXN0Yms1MDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDUwMDAwKSwgXSAgDQp0ZXN0YmsxMDAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMDApLCBdICANCnRlc3RiazE5MDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDE5MDAwMCksIF0gIA0KYGBgDQoNCmFuZCBwbG90DQoNCg0KYGBge3J9DQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IHNzaF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL3NzaF9iYWNrX25vXzE5OTkucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDE5OTksIGFlcyh4ID0gbWxwX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvbWxwX2JhY2tfbm9fMTk5OS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSB0ZW1wX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvdGVtcF9zdXJmYWNlX2JhY2tfbm9fMTk5OS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL3RlbXBfZGVwdGhfYmFja19ub18xOTk5LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IHNhbGluaXR5X3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvc2FsaW5pdHlfc3VyZmFjZV9iYWNrX25vXzE5OTkucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDE5OTksIGFlcyh4ID0gc2FsaW5pdHlfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvc2FsaW5pdHlfZGVwdGhfYmFja19ub18xOTk5LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL2NobF9zdXJmYWNlX2JhY2tfbm9fMTk5OS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBjaGxfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvY2hsX2RlcHRoX2JhY2tfbm9fMTk5OS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBvMl9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL28yX3N1cmZhY2VfYmFja19ub18xOTk5LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL28yX2RlcHRoX2JhY2tfbm9fMTk5OS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQoNCkFuZCBub3cgMjAxNF8wNg0KDQoNCmBgYHtyfQ0Kc3RydCA8LSBTeXMudGltZSgpICNnZXQgdGhlIHN0YXJ0IHRpbWUNCg0KeHkgPC0gdGVzdGJnbGlzdFsgLGMoImxvbmdpdHVkZV8iLCJsYXRpdHVkZV9tIildICMgVGhpcyBpcyB0byB0ZWxsIFIgd2hlcmUgdGhlIGNvb3JkaW5hdGVzIGFyZS4gTm90ZSB0aGF0IHRoZSBjb2x1bW4gb3JkZXIgbmVlZHMgdG8gYmUgbG9uZ2l0dWRlLCBsYXRpdHVkZQ0KdGVzdGJnbGlzdHNwIDwtIFNwYXRpYWxQb2ludHNEYXRhRnJhbWUoY29vcmRzID0geHksIGRhdGEgPSB0ZXN0YmdsaXN0LCBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9YWVhICtsYXRfMT01MCArbGF0XzI9NzAgK2xhdF8wPTQwICtsb25fMD0tNjAgK3hfMD0wICt5XzA9MCArZWxscHM9R1JTODAgK2RhdHVtPU5BRDgzICt1bml0cz1tICtub19kZWZzIikpICMgVGhlIENSUyBpcyB1c2VkIGhlcmUgaXMgZm9yIHRoZSBhbGJlcnMgZXF1YWwgYXJlYSBwcm9qZWN0aW9uLg0KDQoNCm5ldGNkZl9saXN0IDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IFRSVUUpICN0cnVlIG1lYW5zIHRoZSBmdWxsIHBhdGggaXMgaW5jbHVkZWQNCm5vX25ldGNkZiA8LSBsZW5ndGgobmV0Y2RmX2xpc3QpICNmb3IgdGhlIGxvb3AgLSBuZWVkIHRvIGtub3cgaG93IG1hbnkgZmlsZXMgdG8gY3ljbGUgdGhyb3VnaA0KbmV0Y2RmX25hbWUgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9ia3RzdG5jZGYiLCBwYXR0ZXJuID0gJyoubmMnLCBmdWxsLm5hbWVzID0gRkFMU0UpICNmYWxzZSBtZWFucyB0aGUgcGF0aCBpcyBub3QgaW5jbHVkZWQNCmFlYSA8LSByYXN0ZXIoIi4uL291dHB1dC9lbnYvYWVhLnRpZiIpIA0KeXIgPC0gMjAxNCAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24geWVhcg0KbXRoIDwtIDA2ICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiBtb250aA0KDQpmb3IgKGkgaW4gMTpub19uZXRjZGYpIHsgIA0KICBwcmludChuZXRjZGZfbmFtZVtpXSkgI3RoaXMganVzdCBwcmludHMgdGhlIG5hbWUgb2YgdGhlIG5ldENERiBSIGlzIHdvcmtpbmcgb25lDQogIGJya3lyIDwtIGFzLmludGVnZXIoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAxKSkgIyBleHRyYWN0aW5nIHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBuZXRjZGYgZmlsZW5hbWUgKHdoaWNoIGlzIHRoZSB5ZWFyKQ0KICBicmttdGggPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDIpKSAjIGV4dHJhY3RpbmcgdGhlIHNlY29uZCBwYXJ0IG9mIHRoZSBuZXRjZGYgZmlsZW5hbWUgKHdoaWNoIGlzIHRoZSBtb250aCkNCiAgYnJrdmFyIDwtIChzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDMpKSAjIGV4dHJhY3RpbmcgdGhlIHRoaXJkIHBhcnQgb2YgdGhlIG5ldGNkZiAoaW5jLm5jKQ0KICB0ZW1wX2JyaWNrIDwtIGJyaWNrKG5ldGNkZl9saXN0W2ldLCBsdmFyID0gNCkNCiAgdGVtcF9icmljayA8LSBwcm9qZWN0UmFzdGVyKHRlbXBfYnJpY2ssIGFlYSkgDQogICAgZm9yIChqIGluIDE6bnJvdyh0ZXN0YmdsaXN0c3ApKSB7ICANCiAgICAgIGRlIDwtIHRlc3RiZ2xpc3RzcCRkZXB0aGxheWVybm9bW2pdXSAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24gZGVwdGggbGF5ZXINCiAgICAgICAgICBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJ0ZW1wLm5jIil7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKQ0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJzYWxpbml0eS5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNhbGluaXR5X3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNhbGluaXR5X2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNhbGluaXR5X2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJjaGwubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAibzIubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRvMl9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRvMl9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRvMl9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAibWxwLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbWxwX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKQ0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJzc2gubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzc2hfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgDQogICAgICAgICAgfQ0KICAgICANCiAgICB9DQp9DQp3cml0ZS5jc3YodGVzdGJnbGlzdHNwLCAiLi4vZGF0YS9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0XzA2L3Rlc3RiZ2xpc3RvdXRwdXQuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQp0ZXN0X2JhY2tfZGYgPC0gYXMuZGF0YS5mcmFtZSh0ZXN0YmdsaXN0c3ApDQojaGVhZCh0ZXN0X2JhY2tfZGYpDQpwcmludChTeXMudGltZSgpLXN0cnQpICN0aW1lIGl0IHRvb2sgdG8gcnVuDQpgYGANCm9rIG5vdyBjcmVhdGUgdGhlIGZpcnN0IGxvdCBvZiByYW5kb20gZm9yIDIwMTRfMDYNCg0KYGBge3J9DQp0ZXN0YmsxMDAwMDIwMTQgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDEwMDAwKSwgXSAgI3doZXJlIDEwMDAwID0gbnVtYmVyIG9mIHJvd3MgdG8gc2FtcGxlIChsYXJnZSBzYW1wbGUgYXMgcGVyIG1heGVudCkNCnRlc3RiazIwMDAwMjAxNCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMjAwMDApLCBdICANCnRlc3RiazMwMDAwMjAxNCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMzAwMDApLCBdICANCnRlc3RiazUwMDAwMjAxNCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgNTAwMDApLCBdICANCnRlc3RiazEwMDAwMDIwMTQgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDEwMDAwMCksIF0gIA0KdGVzdGJrMTkwMDAwMjAxNCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTkwMDAwKSwgXSAgDQpgYGANCg0KYW5kIHBsb3QNCg0KDQpgYGB7cn0NCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gc3NoX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvc3NoX2JhY2tfbm9fMjAxNC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBtbHBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vZGF0YS9tbHBfYmFja19ub18yMDE0LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IHRlbXBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vZGF0YS90ZW1wX3N1cmZhY2VfYmFja19ub18yMDE0LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IHRlbXBfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvdGVtcF9kZXB0aF9iYWNrX25vXzIwMTQucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gc2FsaW5pdHlfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vZGF0YS9zYWxpbml0eV9zdXJmYWNlX2JhY2tfbm9fMjAxNC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vZGF0YS9zYWxpbml0eV9kZXB0aF9iYWNrX25vXzIwMTQucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gY2hsX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvY2hsX3N1cmZhY2VfYmFja19ub18yMDE0LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IGNobF9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vZGF0YS9jaGxfZGVwdGhfYmFja19ub18yMDE0LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IG8yX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvbzJfc3VyZmFjZV9iYWNrX25vXzIwMTQucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gbzJfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL2RhdGEvbzJfZGVwdGhfYmFja19ub18yMDE0LnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KYGBgDQoNCg0KDQojIDNkIHBsb3QgYmFja2dyb3VuZCBwb2ludHMNCg0KYGBge3J9DQpiY2syMDE0XzA2XzNkIDwtIHBsb3RfbHkoeD0gdGVzdGJrMTAwMDAyMDE0JGxvbmdpdHVkZV8sIHkgPSB0ZXN0YmsxMDAwMDIwMTQkbGF0aXR1ZGVfbSwgeiA9IHRlc3RiazEwMDAwMjAxNCRkZXB0aGxheWVybm8pDQpiY2syMDE0XzA2XzNkDQpgYGANCg0KIyAyZCBwbG90IGJhY2tncm91bmQgcG9pbnRzDQoNCmBgYHtyfQ0KYmNrMjAxNF8wNl8yZCA8LSBwbG90KHg9IHRlc3RiazEwMDAwMjAxNCRsb25naXR1ZGVfLCB5ID0gdGVzdGJrMTAwMDAyMDE0JGxhdGl0dWRlX20pDQpkZXYuY29weShwbmcsIi4uL2RhdGEvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svYmNrMTAwMDBfMmQucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmBgYA==